// Ninf-G-XX, ver. 0.1
// Copyright 2011 National Institute of Advanced Industrial Science and Technology
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <sys/types.h>
#include <rpc/rpc.h>
#include <iostream>
#include "DataInputStream.hpp"
#include "Constants.hpp"
#include "Exception.hpp"

using namespace ninf::lib;

char 
DataInputStream :: readChar(){
  return (char) readInt();
}

short
DataInputStream :: readShort(){
  return (short) readInt();
}

int
DataInputStream :: readInt(){
  int tmp;
  XDR xdr;
  char buf[4];
  
  EBEGIN { is->readFully(buf, 0, 4); } EEND
  xdrmem_create(&xdr, buf, 4, XDR_DECODE);
  if (! xdr_int(&xdr, &tmp))
    EXCEPTION("failed to xdr_int");
  xdr_destroy(&xdr);
  return tmp;
}

long
DataInputStream :: readLong(){
  return readInt();
}

float
DataInputStream :: readFloat(){
  float tmp;
  XDR xdr;
  char buf[4];
  
  EBEGIN { is->readFully(buf, 0, 4); } EEND
  xdrmem_create(&xdr, buf, 4, XDR_DECODE);
  if (! xdr_float(&xdr, &tmp))
    EXCEPTION("failed to xdr_float");
  xdr_destroy(&xdr);
  return tmp;
}

double
DataInputStream :: readDouble(){
  double tmp;
  XDR xdr;
  char buf[8];
  
  EBEGIN { is->readFully(buf, 0, 8); } EEND
  xdrmem_create(&xdr, buf, 8, XDR_DECODE);
  if (! xdr_double(&xdr, &tmp))
    EXCEPTION("failed to xdr_double");
  xdr_destroy(&xdr);
  return tmp;
}

char *
DataInputStream :: readString(){
  int length;

  EBEGIN { length = readInt(); } EEND
  int padlen =  4 - (length % 4);
  if (padlen == 4)
    padlen = 0;
  int buflen = length + padlen + 1;
  
  char * buf = new char[buflen];
  EBEGIN { is->readFully(buf, 0, length + padlen); } EEND

  /** terminate the string */
  *(buf + length) = '\0';
  return buf;
}


void
DataInputStream :: readCharArray(int n, char * c){
  for (int i = 0; i < n; i++)
    *(c+i) = readChar();
}

void
DataInputStream :: readShortArray(int n, short * s){
  for (int i = 0; i < n; i++)
    *(s+i) = readShort();
}


void
DataInputStream :: readIntArray(int n, int * i0){
  for (int i = 0; i < n; i++)
    *(i0+i) = readInt();
}


void
DataInputStream :: readLongArray(int n, long * l){
  for (int i = 0; i < n; i++)
    *(l+i) = readLong();
}


void
DataInputStream :: readFloatArray(int n,  float * f){
  for (int i = 0; i < n; i++)
    *(f+i) = readFloat();
}


void
DataInputStream :: readDoubleArray(int n, double * d){
  for (int i = 0; i < n; i++)
    *(d+i) = readDouble();
}


void
DataInputStream :: readStringArray(int n, char ** s){
  for (int i = 0; i < n; i++)
    *(s+i) = readString();
}

